﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using StripeOne.Core.Models;
using StripeOne.Core.Tools;
using System.Web.Routing;
using StripeOne.Core.Cache;
using System.Xml.Linq;
using StripeOne.Core.Log;
using StripeOne.Blog.Base.Configuration;

namespace StripeOne.Blog.Base.Common
{
    public class Module : StripeOneXml
    {
        #region Constructors
        
        public Module(string section) : base("Modules", section) { }

        #endregion

        #region Public Methods

        public static List<ModuleModel> Modules
        {
            get
            {
                var cacheKey = "Module_AllModules";
                return (List<ModuleModel>)new StripeOneCache().AutoCache<List<ModuleModel>>(cacheKey, CacheTimes.Default.Modules, () => ModulesNoCache(true)).Value;
            }
        }

        public static ModuleModel Default
        {
            get
            {
                return Modules.FirstOrDefault(i => i.IsDefault);
            }
        }

        public static ModuleModel Current
        {
            get
            {
                return SetModule();
            }
        }
        
        #endregion

        #region Private Methods

        private static List<ModuleModel> ModulesNoCache(bool includeInactive = false)
        {
            List<ModuleModel> lstModules = new List<ModuleModel>();
            var xml = StripeOneXml.Load("Modules", false, false);
            var nodes = (from item in xml.Root.Descendants("Module") select item).ToList();

            foreach (var node in nodes)
            {
                var alreadyDefault = lstModules.Any(i => i.IsDefault);

                var module = new ModuleModel();
                module.Id = node.GetAttribute("id").ToInt32();
                //Only one module can be default, the first to have the attribute is the default
                module.IsDefault = alreadyDefault ? false : node.GetAttribute("default").ToBoolean();
                module.Code = node.GetElement("Code");
                module.Name = node.GetElement("Name");
                module.UrlSufix = node.GetElement("UrlSufix");
                module.ControllerPrefix = node.GetElement("ControllerPrefix");
                module.Active = node.GetElement("Active").ToBoolean();

                lstModules.Add(module);
            }

            return includeInactive ? lstModules : lstModules.Where(i => i.Active).ToList();
        }

        private static ModuleModel SetModule()
        {
            try
            {
                var cache = new StripeOneCache();
                string cacheKey = "StripeOneInstances_SetInstance_" + GetModuleCode();
                return (ModuleModel)cache.AutoCache<ModuleModel>(cacheKey, CacheTimes.Default.Modules, () => SetModuleNoCache()).Value;
            }
            catch (Exception ex)
            {
                StripeOneLog.Exception(ex);
                return null;
            }
        }

        private static ModuleModel SetModuleNoCache()
        {
            var result = new ModuleModel();
            var currentModuleCode = GetModuleCode();

            result = Modules.FirstOrDefault(i => i.Code.Equals(currentModuleCode, StringComparison.InvariantCultureIgnoreCase));

            return result ?? new ModuleModel();
        }

        private static string GetModuleCode()
        {
            var routes = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));
            var productCode = routes.Values.FirstOrDefault(i => i.Key.Equals("moduleCode"));
            return productCode.Value != null ? productCode.Value.ToString() : "";
        }

        #endregion
    }
}